package com.xbongbong.paas.service.stage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.BusinessRuleConditionHelp;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkflowEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.FilterConditionsPoJo;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.pro.enums.errorcodes.BusinessRuleErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerStageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.saas.help.StageHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.model.StageWorkflowModel;
import com.xbongbong.paas.pojo.ExecutionEventLinkDataPojo;
import com.xbongbong.paas.pojo.ExecutionEventPojo;
import com.xbongbong.paas.pojo.StageConditionLintAttrPojo;
import com.xbongbong.paas.pojo.StageConditionPojo;
import com.xbongbong.paas.pojo.StageExtraSettingPojo;
import com.xbongbong.paas.pojo.StageWorkflowPojo;
import com.xbongbong.paas.pojo.vo.StageGetVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.condition.ProConditionHelp;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.StageProcessConstant;
import com.xbongbong.pro.enums.businessrule.enums.RuleValueTypeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.StageWorkEntity;
import com.xbongbong.saas.enums.ExecutionEventEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.model.WorkflowModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 阶段设置
 * @author 李少杰
 * @version v1.0.0
 * @date 2021/11/22 11:11
 */
@Service("abstractStageSettingsStrategy")
public class AbstractStageSettingsStrategy {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractStageSettingsStrategy.class);

    @Resource
    private StageHelp stageHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;
    @Resource
    private LogHelp logHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private StageWorkflowModel stageWorkflowModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private PackageHelp packageHelp;

    /**
     * 封装entity数据，使用set 避免使用beanCopy
     * @param paasStageEntity 表单实体
     * @return stageGetVO
     */
    public StageGetVO wrapStageEntity(PaasStageEntity paasStageEntity) throws XbbException {
        if (Objects.isNull(paasStageEntity)) {
            return null;
        }
        StageGetVO stageGetVO = new StageGetVO();
        stageGetVO.setId(paasStageEntity.getId());
        stageGetVO.setName(paasStageEntity.getName());
        stageGetVO.setCode(paasStageEntity.getCode());
        stageGetVO.setIntoProportion(paasStageEntity.getIntoProportion());
        stageGetVO.setOutProportion(paasStageEntity.getOutProportion());
        stageGetVO.setType(paasStageEntity.getType());
        stageGetVO.setEnable(paasStageEntity.getEnable());
        stageGetVO.setSort(paasStageEntity.getSort());
        stageGetVO.setStayLimit(Objects.isNull(paasStageEntity.getStayLimit()) ? 0 : paasStageEntity.getStayLimit());
        if (Objects.equals(paasStageEntity.getStayLimit(), 1)) {
            stageGetVO.setStayLimitTimeUnit(paasStageEntity.getStayLimitTimeUnit());
            stageGetVO.setStayLimitTime(paasStageEntity.getStayLimitTime());
        }
        stageGetVO.setEnableStageWarningColor(Objects.isNull(paasStageEntity.getEnableStageWarningColor()) ? 0 : paasStageEntity.getEnableStageWarningColor());
        if (Objects.equals(paasStageEntity.getEnableStageWarningColor(), 1)) {
            stageGetVO.setStageWarningColor(paasStageEntity.getStageWarningColor());
        }
        JSONArray executor = Objects.isNull(paasStageEntity.getExecutor()) ? new JSONArray() : paasStageEntity.getExecutor();
        stageGetVO.setExecutor(executor.toJavaList(OptionalRangeEntity.class));
        JSONArray preConditions = Objects.isNull(paasStageEntity.getPreConditions()) ? new JSONArray() : JSONArray.parseArray(paasStageEntity.getPreConditions());
        stageGetVO.setPreConditions(preConditions.toJavaList(StageConditionPojo.class));
        stageGetVO.setAllowSkipStage(paasStageEntity.getAllowSkipStage());
        stageGetVO.setOpenStatus(paasStageEntity.getOpenStatus());
        stageGetVO.setBusinessRelatedStatus(paasStageEntity.getBusinessRelatedStatus());
        stageGetVO.setAllowReactive(paasStageEntity.getAllowReactive());
        JSONArray allowReactiveStage = Objects.isNull(paasStageEntity.getAllowReactiveStage()) ? new JSONArray() : paasStageEntity.getAllowReactiveStage();
        stageGetVO.setAllowReactiveStage(allowReactiveStage.toJavaList(Long.class));
        stageGetVO.setEnableAutoJump(Objects.isNull(paasStageEntity.getEnableAutoJump()) ? 0 : paasStageEntity.getEnableAutoJump());
        stageGetVO.setEnableJumpEnd(Objects.isNull(paasStageEntity.getEnableJumpEnd()) ? 1 : paasStageEntity.getEnableJumpEnd());
        stageGetVO.setIsDefault(paasStageEntity.getIsDefault());
        stageGetVO.setLinkOption(paasStageEntity.getLinkOption());
        StageExtraSettingPojo stageExtraSettingPojo = Objects.isNull(paasStageEntity.getExtraSetting()) ? null : JSONObject.parseObject(JSON.toJSONString(paasStageEntity.getExtraSetting()), StageExtraSettingPojo.class);
        stageGetVO.setStageExtraSettingPojo(stageExtraSettingPojo);

        //封装自定义工作流
        if (packageHelp.isUltimateWithFeeType(paasStageEntity.getCorpid())) {
            List<StageWorkflowPojo> stageWorkflow = getStageWorkflow(paasStageEntity.getCorpid(), paasStageEntity.getFormId(), paasStageEntity.getStageProcessId(), paasStageEntity.getId());
            stageGetVO.setStageWorkflowPojoList(stageWorkflow);
        }
        return stageGetVO;
    }

    /**
     * 获取阶段工作流设置
     * @return pojoList
     */
    protected List<StageWorkflowPojo> getStageWorkflow(String corpid, Long formId, Long stageProcessId, Long stageId) {
        Map<String, Object> params = new HashMap<>(2 << 2);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.STAGE_ID, stageId);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<StageWorkflowEntity> stageWorkflowEntityList = stageWorkflowModel.findEntitys(params);
        if (CollectionsUtil.isEmpty(stageWorkflowEntityList)) {
            return null;
        }
        List<Long> workFlowIdList = stageWorkflowEntityList.stream().map(StageWorkflowEntity::getWorkflowId).collect(Collectors.toList());
        params.clear();
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(StringConstant.IDIN, workFlowIdList);
        List<WorkflowEntity> workflowEntityList = workflowModel.findEntitys(params);
        Map<Long, WorkflowEntity> workflowEntityMap = null;
        if (CollectionsUtil.isNotEmpty(workflowEntityList)) {
            workflowEntityMap = workflowEntityList.stream().collect(Collectors.toMap(WorkflowEntity::getId, t -> t, (t, t1) -> t1));
        }
        List<StageWorkflowPojo> stageWorkflowPojoList = new ArrayList<>(stageWorkflowEntityList.size());
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            StageWorkflowPojo stageWorkflowPojo = new StageWorkflowPojo();
            stageWorkflowPojo.setId(stageWorkflowEntity.getId());
            stageWorkflowPojo.setWorkflowId(stageWorkflowEntity.getWorkflowId());
            stageWorkflowPojo.setTriggerType(stageWorkflowEntity.getTriggerType());
            stageWorkflowPojo.setRelatedStageId(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(workflowEntityMap)) {
                WorkflowEntity workflowEntity = workflowEntityMap.get(stageWorkflowEntity.getWorkflowId());
                if (Objects.nonNull(workflowEntity)) {
                    stageWorkflowPojo.setWorkflowName(workflowEntity.getName());
                }
            }
            stageWorkflowPojoList.add(stageWorkflowPojo);
        }
        return stageWorkflowPojoList;
    }

    /**
     * 获取各类型的阶段封装
     * @param paasStageEntityList 阶段实体列表
     * @return Map<Integer, List<PaasStageEntity>>
     * @throws XbbException exception
     */
    public Map<Integer, List<PaasStageEntity>> getStageMap(List<PaasStageEntity> paasStageEntityList) throws XbbException {
        if (CollectionsUtil.isEmpty(paasStageEntityList)) {
            return new HashMap<>();
        }
        //自然降序
        paasStageEntityList = paasStageEntityList.stream().sorted(Comparator.comparing(PaasStageEntity::getSort).reversed()).collect(Collectors.toList());
        Map<Integer, List<PaasStageEntity>> stageMap = new HashMap<>(2 << 1);
        List<PaasStageEntity> ordinaryStageEntityList = new ArrayList<>();
        List<PaasStageEntity> successStageEntityList = new ArrayList<>();
        List<PaasStageEntity> failStageEntityList = new ArrayList<>();
        List<PaasStageEntity> cancelStageEntityList = new ArrayList<>();

        //名称重复校验
        List<String> nameList = paasStageEntityList.stream().map(PaasStageEntity::getName).collect(Collectors.toList());
        long count = nameList.stream().distinct().count();
        if (nameList.size() != count) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238008);
        }

        PaasStageEntity lastStage = null;
        for (PaasStageEntity paasStageEntity : paasStageEntityList) {
            StageTypeEnum stageTypeEnum = StageTypeEnum.getByType(paasStageEntity.getType());
            if (Objects.isNull(stageTypeEnum)) {
                continue;
            }
            switch (stageTypeEnum) {
                case ORDINARY_STAGE:
                    if (Objects.nonNull(lastStage) && !Objects.equals(lastStage.getType(), stageTypeEnum.getType())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238015);
                    }
                    ordinaryStageEntityList.add(paasStageEntity);
                    break;
                case FAIL_STAGE:
                    failStageEntityList.add(paasStageEntity);
                    break;
                case SUCCESS_STAGE:
                    successStageEntityList.add(paasStageEntity);
                    break;
                case CANCEL_STAGE:
                    cancelStageEntityList.add(paasStageEntity);
                default:
                    break;
            }
            lastStage = paasStageEntity;
        }
        stageMap.put(StageTypeEnum.ORDINARY_STAGE.getType(), ordinaryStageEntityList);
        stageMap.put(StageTypeEnum.SUCCESS_STAGE.getType(), successStageEntityList);
        stageMap.put(StageTypeEnum.FAIL_STAGE.getType(), failStageEntityList);
        stageMap.put(StageTypeEnum.CANCEL_STAGE.getType(), cancelStageEntityList);
        return stageMap;
    }

    /**
     * 校验阶段任务
     * @param paasStageEntity 阶段实体
     * @param stageWorkEntityList 阶段任务实体列表
     * @throws XbbException exception
     */
    public void checkStageWork(PaasStageEntity paasStageEntity, List<StageWorkEntity> stageWorkEntityList) throws XbbException {
        if (Objects.isNull(paasStageEntity) || CollectionsUtil.isEmpty(stageWorkEntityList)) {
            return;
        }
        Integer type = paasStageEntity.getType();
        Integer intoProportion = paasStageEntity.getIntoProportion();
        Integer outProportion = paasStageEntity.getOutProportion();
        Integer stageWorkProportionSum = 0;

        //用来标识当前新增或者编辑的任务的信息
        Integer editStageWorkProportion = 0;
        String editStageWorkName = "";
        boolean isEditStageWork = false;
        if (stageWorkEntityList.size() > StageProcessConstant.STAGE_WORK_MAX_COUNT) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238062, CustomerStageErrorCodeEnum.API_ERROR_238062.getMsg(), StageProcessConstant.STAGE_WORK_MAX_COUNT, I18nMessageUtil.getMessage(I18nStringConstant.STAGE_WORK));
        }
        for (StageWorkEntity stageWorkEntity : stageWorkEntityList) {
            //结束阶段 不允许设置阶段任务比例
            if (!Objects.equals(StageTypeEnum.getByType(type), StageTypeEnum.ORDINARY_STAGE)) {
                if (Objects.nonNull(stageWorkEntity.getProportion()) && ! Objects.equals(stageWorkEntity.getProportion(), BasicConstant.ZERO)) {
                    throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238022);
                }
                stageWorkEntity.setProportion(BasicConstant.ZERO);
            } else {
                if (Objects.isNull(stageWorkEntity.getProportion())) {
                    throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238047);
                }
                stageWorkProportionSum += stageWorkEntity.getProportion();
            }
            if (Objects.equals(stageWorkEntity.getIsEdit(), true)) {
                editStageWorkProportion = stageWorkEntity.getProportion();
                editStageWorkName = stageWorkEntity.getName();
                isEditStageWork = true;
            }
        }
        stageWorknormalCheck(stageWorkEntityList);
        if (intoProportion + stageWorkProportionSum > outProportion) {
            // 区分两种提示用户信息场景
            if (Objects.equals(isEditStageWork, true)) {
                Integer remindPropotion = outProportion - intoProportion - (stageWorkProportionSum - editStageWorkProportion);
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238068, String.format(CustomerStageErrorCodeEnum.API_ERROR_238068.getMsg(), editStageWorkName, remindPropotion));
            }else {
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238021, CustomerStageErrorCodeEnum.API_ERROR_238021.getMsg());
            }
        }
    }

    /**
     * 阶段通用强校验
     * @param paasStageEntityList 阶段实体
     * @throws XbbException exception
     */
    public void stageNormalCheck(Integer businessType, List<PaasStageEntity> paasStageEntityList) throws XbbException {
        if (CollectionsUtil.isEmpty(paasStageEntityList)) {
            return;
        }
        String corpid = paasStageEntityList.get(0).getCorpid();
        Long formId = paasStageEntityList.get(0).getFormId();
        Set<Long> formIdSet = new HashSet<>();
        Set<Long> workOrderFormIdSet = new HashSet<>();
        List<StageConditionPojo> allStageConditionPojoList = new ArrayList<>();

        for (PaasStageEntity paasStageEntity : paasStageEntityList) {
            if (Objects.isNull(paasStageEntity)) {
                return;
            }
            if (Objects.isNull(paasStageEntity.getCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_CODE_NOT_NULL);
            }
            if (Objects.isNull(paasStageEntity.getName())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_NAME_NOT_NULL);
            }
            if (Objects.isNull(paasStageEntity.getOutProportion())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROPORTION_NOT_NULL);
            }
            if (Objects.isNull(paasStageEntity.getEnable()) || Objects.equals(EnableEnum.UNKNOWN, EnableEnum.getByCode(paasStageEntity.getEnable()))) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_RNABLE_NOT_NULL);
            }
            if (Objects.isNull(paasStageEntity.getType())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_TYPE_NOT_NULL);
            }
            if (Objects.isNull(StageTypeEnum.getByType(paasStageEntity.getType()))) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_TYPE_ERROR);
            }
            if (Objects.isNull(paasStageEntity.getSort())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_SORT_NOT_NULL);
            }
            JSONArray preConditions = Objects.isNull(paasStageEntity.getPreConditions()) ? new JSONArray() : JSONArray.parseArray(paasStageEntity.getPreConditions());
            List<StageConditionPojo> stageConditionPojoList = preConditions.toJavaList(StageConditionPojo.class);
            if (CollectionsUtil.isNotEmpty(stageConditionPojoList)) {
                if (stageConditionPojoList.size() > StageProcessConstant.STAGE_PRE_CONDITIONS_MAX_COUNT) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PRE_CONDITIONS_SIZE, StageProcessConstant.STAGE_PRE_CONDITIONS_MAX_COUNT);
                }
                for (StageConditionPojo stageConditionPojo : stageConditionPojoList) {
                    if (StringUtil.isEmpty(stageConditionPojo.getName()) || stageConditionPojo.getName().length() > StageProcessConstant.STAGE_CONDITION_NAME_MAX ) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238059, CustomerStageErrorCodeEnum.API_ERROR_238059.getMsg(), paasStageEntity.getName());
                    }
                    if (Objects.isNull(stageConditionPojo.getLinkAttr())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238060, CustomerStageErrorCodeEnum.API_ERROR_238060.getMsg(), paasStageEntity.getName() + "（" + stageConditionPojo.getName() + ")");
                    }
                    if (CollectionsUtil.isEmpty(stageConditionPojo.getFilter())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238061, CustomerStageErrorCodeEnum.API_ERROR_238061.getMsg(), paasStageEntity.getName() + "（" + stageConditionPojo.getName() + ")");
                    }
                    StageConditionLintAttrPojo linkAttr = stageConditionPojo.getLinkAttr();
                    Integer linkBusinessType = linkAttr.getBusinessType();
                    if (Objects.nonNull(linkBusinessType) && Objects.equals(linkBusinessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                        workOrderFormIdSet.add(linkAttr.getFormId());
                    } else {
                        formIdSet.add(linkAttr.getFormId());
                    }
                }
                allStageConditionPojoList.addAll(stageConditionPojoList);
            }
        }

        if (CollectionsUtil.isNotEmpty(allStageConditionPojoList)) {
            Map<Long, PaasFormExplainEntity> formExplainMap = new HashMap<>();
            Map<Long, Map<String, FieldAttrEntity>> workOrderFormFieldMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(formIdSet)) {
                formExplainMap = proFormHelp.getFormExplainMap(formIdSet, corpid);
            }
            if (CollectionsUtil.isNotEmpty(workOrderFormIdSet)) {
                workOrderFormFieldMap = proFormHelp.getWorkOrderFormFieldMap(workOrderFormIdSet, corpid);
            }
            PaasFormExplainEntity explainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explainEntity.getExplains(), null);
            for (StageConditionPojo stageConditionPojo : allStageConditionPojoList) {
                validateStagePreCondition(formId, businessType, stageConditionPojo, explainMap, formExplainMap, workOrderFormFieldMap);
            }
        }
    }

    /**
     * 阶段任务通用强校验
     * @param stageWorkEntityList 阶段任务实体
     * @throws XbbException exception
     */
    protected void stageWorknormalCheck(List<StageWorkEntity> stageWorkEntityList) throws XbbException {
        if (CollectionsUtil.isEmpty(stageWorkEntityList)) {
            return;
        }
        String corpid = stageWorkEntityList.get(0).getCorpid();
        Long formId = stageWorkEntityList.get(0).getFormId();
        List<StageConditionPojo> allStageConditionPojoList = new ArrayList<>();

        for (StageWorkEntity stageWorkEntity : stageWorkEntityList) {
            if (Objects.isNull(stageWorkEntity)) {
                return;
            }
            if (Objects.isNull(stageWorkEntity.getProportion())) {
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238047);
            }
            if (Objects.isNull(stageWorkEntity.getName())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_WORK_NAME_NOT_NULL);
            }
            if (Objects.isNull(stageWorkEntity.getRequired())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_WORK_REQUIRE_NOT_NULL);
            }
            JSONObject executionEvent = stageWorkEntity.getExecutionEvent();
            if (Objects.nonNull(executionEvent)) {
                ExecutionEventPojo executionEventPojo = executionEvent.toJavaObject(ExecutionEventPojo.class);
                Integer type = executionEventPojo.getType();
                if (Objects.isNull(type)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_WORK_EXECUTION_EVENT_TYPE_NOT_NULL);
                }
                if (Objects.equals(type, ExecutionEventEnum.FIELDATTR_EDIT.getType()) && CollectionsUtil.isEmpty(executionEventPojo.getFieldList())) {
                    throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238057, CustomerStageErrorCodeEnum.API_ERROR_238057.getMsg(), stageWorkEntity.getName());
                }
                if (Objects.equals(type, ExecutionEventEnum.LINK_DATA_EDIT.getType())) {
                    ExecutionEventLinkDataPojo linkData = executionEventPojo.getLinkData();
                    if (Objects.isNull(linkData) ||
                            Objects.isNull(linkData.getFormId()) ||
                            StringUtil.isEmpty(linkData.getAttr()) ||
                            CollectionsUtil.isEmpty(linkData.getFieldList())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238058, CustomerStageErrorCodeEnum.API_ERROR_238058.getMsg(), stageWorkEntity.getName());
                    }
                }
            }
            JSONArray completionCondition = Objects.isNull(stageWorkEntity.getCompletionCondition()) ? new JSONArray() : stageWorkEntity.getCompletionCondition();
            List<StageConditionPojo> stageConditionPojos = completionCondition.toJavaList(StageConditionPojo.class);
            if (CollectionsUtil.isNotEmpty(stageConditionPojos)) {
                for (StageConditionPojo stageConditionPojo : stageConditionPojos) {
                    if (StringUtil.isEmpty(stageConditionPojo.getName()) || stageConditionPojo.getName().length() > StageProcessConstant.STAGE_CONDITION_NAME_MAX) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238064);
                    }
                    if (CollectionsUtil.isEmpty(stageConditionPojo.getFilter())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238065);
                    }
                }
                allStageConditionPojoList.addAll(stageConditionPojos);
            }
        }
        if (CollectionsUtil.isNotEmpty(allStageConditionPojoList)) {
            Map<Long, PaasFormExplainEntity> formExplainMap = proFormHelp.getFormExplainMap(Collections.singletonList(formId), corpid);
            for (StageConditionPojo stageConditionPojo : allStageConditionPojoList) {
                PaasFormExplainEntity paasFormExplainEntity = formExplainMap.get(formId);
                Map<String, FieldAttrEntity> thisExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                String message = I18nMessageUtil.getMessage(I18nStringConstant.STAGE_COMPLETION_CONDITION) + "（" + stageConditionPojo.getName() + "）";
                BusinessRuleConditionHelp.validateStagePreCondition(stageConditionPojo.getFilter(), thisExplainMap, message);
            }
        }
    }

    /**
     * 校验阶段进入条件及完成条件
     * @param formId 表单id
     * @param businessType 业务类型
     * @param stageConditionPojo 阶段条件
     * @param explainMap 本表解释
     * @param targetFormExplainMap 目标表解释
     * @param workOrderFormFieldMap 工单解释
     * @throws XbbException exception
     */
    protected void validateStagePreCondition(Long formId, Integer businessType, StageConditionPojo stageConditionPojo, Map<String, FieldAttrEntity> explainMap, Map<Long, PaasFormExplainEntity> targetFormExplainMap, Map<Long, Map<String, FieldAttrEntity>> workOrderFormFieldMap) throws XbbException {
        StageConditionLintAttrPojo linkAttr = stageConditionPojo.getLinkAttr();
        if (Objects.isNull(linkAttr)) {
            linkAttr = new StageConditionLintAttrPojo(BasicConstant.ONE, formId, null, null, businessType);
        }
        List<FilterConditionsPoJo> conditionPojoFilter = stageConditionPojo.getFilter();
        Integer type = linkAttr.getType();
        Long linkFormId = linkAttr.getFormId();
        Integer linkBusinessType = linkAttr.getBusinessType();
        String message = I18nMessageUtil.getMessage(I18nStringConstant.STAGE_INTO_CONDITION) + "（" + stageConditionPojo.getName() + "）";
        if (Objects.equals(type, BasicConstant.ONE)) {
            //本表
            if (Objects.nonNull(explainMap)) {
                BusinessRuleConditionHelp.validateStagePreCondition(stageConditionPojo.getFilter(), explainMap, message);
            }
        } else if (Objects.equals(type, BasicConstant.TWO)) {
            //关联表
            Map<String, FieldAttrEntity> targetFieldAttrEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(linkBusinessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                targetFieldAttrEntityMap = workOrderFormFieldMap.get(linkFormId);
            } else {
                PaasFormExplainEntity paasFormExplainEntity = targetFormExplainMap.get(linkFormId);
                if (Objects.nonNull(paasFormExplainEntity)) {
                    targetFieldAttrEntityMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                }
            }
            ProFormHelp.setDataIdAttr(targetFieldAttrEntityMap);
            validateFilterCondition(conditionPojoFilter, linkAttr, explainMap, targetFieldAttrEntityMap, formId, businessType, message);
        }
    }

    /**
     * 校验条件
     * @param filterConditions 进入条件列表
     * @param linkAttr 关联信息
     * @param explainMap 本表解释
     * @param targetExplain 目标表解释
     * @param formId 表单id
     * @param businessType 业务类型
     * @throws XbbException exception
     */
    public void validateFilterCondition(List<FilterConditionsPoJo> filterConditions, StageConditionLintAttrPojo linkAttr, Map<String, FieldAttrEntity> explainMap, Map<String, FieldAttrEntity> targetExplain, Long formId, Integer businessType, String titleMsg) throws XbbException {
        if (CollectionUtils.isEmpty(filterConditions)) {
            throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261005);
        }
        for (FilterConditionsPoJo item : filterConditions) {
            if (StringUtil.isEmpty(item.getAttr())) {
                throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261001, titleMsg + BusinessRuleErrorCodeEnum.API_ERROR_261001.getMsg());
            }
            String attr = item.getAttr();
            FieldAttrEntity targetField;

            targetField = targetExplain.get(attr);
            if (Objects.equals(item.getValueType(), RuleValueTypeEnum.DYNAMIC_VALUE.getType())) {
                String valueAttr = item.getValueAttr();
                if (StringUtil.isEmpty(valueAttr)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261001, titleMsg + BusinessRuleErrorCodeEnum.API_ERROR_261001.getMsg());
                }
                FieldAttrEntity fieldAttrEntity = explainMap.get(valueAttr);
                if (Objects.isNull(fieldAttrEntity)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006, titleMsg + BusinessRuleErrorCodeEnum.API_ERROR_261006.getMsg());
                }
                if (Objects.isNull(targetField)) {
                    throw new XbbException(BusinessRuleErrorCodeEnum.API_ERROR_261006, titleMsg + BusinessRuleErrorCodeEnum.API_ERROR_261006.getMsg());
                }
                // 校验关联数据、系统关联字段和dataId之间的关联关系
                ProConditionHelp.validateTheForm(targetField, fieldAttrEntity, linkAttr.getBusinessType(), linkAttr.getSaasMark(), formId, linkAttr.getFormId(), businessType);
            } else {
                // 固定值
                if (Objects.isNull(item.getValue()) || StringUtil.isEmpty(item.getValue().toString())) {
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260047, String.format(ProErrorCodeEnum.API_ERROR_260047.getMsg(), titleMsg, item.getAttrName()));
                }
            }
        }
    }

    /**
     * 记录阶段设置变更日志
     * @param baseDTO dto
     * @param formId 表单id
     * @param oldStageEntityList 修改前阶段实体列表
     * @param newStageEntityList 修改后阶段实体列表
     */
    public void saveStageLog(BaseDTO baseDTO, Long formId, List<PaasStageEntity> oldStageEntityList, List<PaasStageEntity> newStageEntityList) {
        Runnable runnable = () -> {
            try {
                String corpid = baseDTO.getCorpid();
                PaasFormEntityExt paasFormEntityExt = stageHelp.getPaasFormEntity(corpid, formId);
                if (CollectionsUtil.isEmpty(newStageEntityList)) {
                    // 删除阶段
                    for (PaasStageEntity paasStageEntity : oldStageEntityList) {
                        JSONObject oldObj = JSONObject.parseObject(JSONObject.toJSONString(paasStageEntity));
                        List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE, oldObj, new JSONObject());
                        if (Objects.nonNull(detailArr)) {
                            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                            String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                        }
                    }
                    return;
                }
                // 修改与新增阶段
                Map<Long, PaasStageEntity> oldPaasStageEntityMap;
                if (CollectionsUtil.isEmpty(oldStageEntityList)) {
                    oldPaasStageEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                } else {
                    oldPaasStageEntityMap = new HashMap<>(oldStageEntityList.size());
                    for (PaasStageEntity paasStageEntity : oldStageEntityList) {
                        if (Objects.nonNull(paasStageEntity)) {
                            oldPaasStageEntityMap.put(paasStageEntity.getId(), paasStageEntity);
                        }
                    }
                }
                for (PaasStageEntity paasStageEntity : newStageEntityList) {
                    PaasStageEntity oldStageEntity = oldPaasStageEntityMap.get(paasStageEntity.getId());
                    JSONObject oldObj = Objects.isNull(oldStageEntity) ? new JSONObject() : JSONObject.parseObject(JSONObject.toJSONString(oldStageEntity));
                    JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(paasStageEntity));

                    List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE, oldObj, newObj);
                    if (CollectionsUtil.isNotEmpty(detailArr)) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                        String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                    }
                }
            } catch (Exception e) {
                LOG.error("阶段推进器-阶段设置变更记录日志失败!", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
    }

    /**
     * 阶段任务日志
     * @param baseDTO dto
     * @param formId 表单id
     * @param oldStageWorkEntityList 修改前阶段任务列表
     * @param newStageWorkEntityList 修改后阶段任务列表
     */
    public void saveStageWorkLog(BaseDTO baseDTO, Long formId, List<StageWorkEntity> oldStageWorkEntityList, List<StageWorkEntity> newStageWorkEntityList) {
        Runnable runnable = () -> {
            try {
                String corpid = baseDTO.getCorpid();
                PaasFormEntityExt paasFormEntityExt = stageHelp.getPaasFormEntity(corpid, formId);
                if (CollectionsUtil.isEmpty(newStageWorkEntityList)) {
                    // 删除阶段
                    for (StageWorkEntity stageWorkEntity : oldStageWorkEntityList) {
                        JSONObject oldObj = JSONObject.parseObject(JSONObject.toJSONString(stageWorkEntity));
                        List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE_WORK, oldObj, new JSONObject());
                        if (Objects.nonNull(detailArr)) {
                            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                            String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                        }
                    }
                    return;
                }
                // 修改与新增阶段
                Map<Long, StageWorkEntity> oldStageWorkEntityMap;
                if (CollectionsUtil.isEmpty(oldStageWorkEntityList)) {
                    oldStageWorkEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                } else {
                    oldStageWorkEntityMap = new HashMap<>(oldStageWorkEntityList.size());
                    for (StageWorkEntity stageWorkEntity : oldStageWorkEntityList) {
                        if (Objects.nonNull(stageWorkEntity)) {
                            oldStageWorkEntityMap.put(stageWorkEntity.getId(), stageWorkEntity);
                        }
                    }
                }
                for (StageWorkEntity stageWorkEntity : newStageWorkEntityList) {
                    StageWorkEntity oldStageWorkEntity = oldStageWorkEntityMap.get(stageWorkEntity.getId());
                    JSONObject oldObj = Objects.isNull(oldStageWorkEntity) ? new JSONObject() : JSONObject.parseObject(JSONObject.toJSONString(oldStageWorkEntity));
                    JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(stageWorkEntity));

                    List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE_WORK, oldObj, newObj);
                    if (CollectionsUtil.isNotEmpty(detailArr)) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                        String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                    }
                }
            } catch (Exception e) {
                LOG.error("阶段推进器-阶段任务设置变更记录日志失败!", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
    }

    /**
     * 阶段流程日志
     * @param baseDTO dto
     * @param formId 表单id
     * @param oldStageProcessEntityList 修改前阶段流程实体列表
     * @param newStageProcessEntityList 修改后阶段流程实体列表
     */
    public void saveStageProcessLog(BaseDTO baseDTO, Long formId, List<StageProcessEntity> oldStageProcessEntityList, List<StageProcessEntity> newStageProcessEntityList) {
        Runnable runnable = () -> {
            try {
                String corpid = baseDTO.getCorpid();
                PaasFormEntityExt paasFormEntityExt = stageHelp.getPaasFormEntity(corpid, formId);
                if (CollectionsUtil.isEmpty(newStageProcessEntityList)) {
                    // 删除阶段
                    for (StageProcessEntity stageProcessEntity : oldStageProcessEntityList) {
                        JSONObject oldObj = JSONObject.parseObject(JSONObject.toJSONString(stageProcessEntity));
                        List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE_PROCESS, oldObj, new JSONObject());
                        if (Objects.nonNull(detailArr)) {
                            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                            String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                        }
                    }
                    return;
                }
                // 修改与新增阶段
                Map<Long, StageProcessEntity> oldStageProcessEntityMap;
                if (CollectionsUtil.isEmpty(oldStageProcessEntityList) || Objects.isNull(oldStageProcessEntityList.get(0))) {
                    oldStageProcessEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                } else {
                    oldStageProcessEntityMap = new HashMap<>(oldStageProcessEntityList.size());
                    for (StageProcessEntity stageProcessEntity : oldStageProcessEntityList) {
                        if (Objects.nonNull(stageProcessEntity)) {
                            oldStageProcessEntityMap.put(stageProcessEntity.getId(), stageProcessEntity);
                        }
                    }
                }
                for (StageProcessEntity stageProcessEntity : newStageProcessEntityList) {
                    StageProcessEntity oldStageProcessEntity = oldStageProcessEntityMap.get(stageProcessEntity.getId());
                    JSONObject oldObj = Objects.isNull(oldStageProcessEntity) ? new JSONObject() : JSONObject.parseObject(JSONObject.toJSONString(oldStageProcessEntity));
                    JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(stageProcessEntity));

                    List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.STAGE_PROCESS, oldObj, newObj);
                    if (CollectionsUtil.isNotEmpty(detailArr)) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_EXPLAIN), baseDTO.getLoginUserName(), paasFormEntityExt.getName());
                        String opObjectName = paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.FIELD_EXPLAIN);
                        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, baseDTO.getUserId(), baseDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, baseDTO.getHttpHeader());
                    }
                }
            } catch (Exception e) {
                LOG.error("阶段推进器-阶段流程设置变更记录日志失败!", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
    }
}
